home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 February: Tool Chest / Dev.CD Feb 94.toast / Tool Chest / Development Platforms / AppsToGo / AppsToGo.src / DTS.StyleChat / AECustom.c next >
Encoding:
C/C++ Source or Header  |  1993-06-18  |  10.5 KB  |  383 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** File:        AECustom.c
  5. ** Written by:    Eric Soldan
  6. **
  7. ** Copyright © 1990-1991 Apple Computer, Inc.
  8. ** All rights reserved.
  9. */
  10.  
  11.  
  12.  
  13. /*****************************************************************************/
  14.  
  15.  
  16.  
  17. #include "App.h"            /* Get the application includes/typedefs, etc.    */
  18. #include "App.defs.h"        /* Get various application definitions.            */
  19. #include "App.protos.h"        /* Get the prototypes for application.            */
  20.  
  21. #ifndef __ERRORS__
  22. #include <Errors.h>
  23. #endif
  24.  
  25. #ifndef __TEXTEDITCONTROL__
  26. #include "TextEditControl.h"
  27. #endif
  28.  
  29. #ifndef __UTILITIES__
  30. #include "Utilities.h"
  31. #endif
  32.  
  33.  
  34.  
  35. /*****************************************************************************/
  36.  
  37.  
  38.  
  39. extern Boolean        gHasAppleEvents;
  40.     /* This is defined and initialized by the DTS.Lib..framework file AERequired.c.
  41.     ** This means that InitRequiredAppleEvents must be called prior to calling
  42.     ** InitConnectAppleEvents (a DTS.Lib..framework function), or before calling
  43.     ** InitCustomAppleEvents (a DTS.StyleChat function). */
  44.  
  45.  
  46. static pascal OSErr        ReceiveMessage(AppleEvent *message, AppleEvent *reply, long refcon);
  47.  
  48.  
  49.  
  50. /*****************************************************************************/
  51.  
  52.  
  53.  
  54. static AEHandler keywordsToInstall[] = {
  55.     { kCustomEventClass, keyAppMessage, ReceiveMessage }
  56. };        /* These are the custom AppleEvents. */
  57.  
  58.  
  59.  
  60. /*****************************************************************************/
  61. /*****************************************************************************/
  62.  
  63.  
  64.  
  65. /* Install our custom AppleEvents.  This is done in addition to installing
  66. ** the required AppleEvents.  InitAppleEvents, which installs the required
  67. ** AppleEvents, must be called first, since it sets up some global values. */
  68.  
  69. #pragma segment AppleEvents
  70. void    InitCustomAppleEvents(void)
  71. {
  72.     OSErr    err;
  73.     short    i;
  74.  
  75.     if (gHasAppleEvents) {
  76.         for (i = 0; i < (sizeof(keywordsToInstall) / sizeof(AEHandler)); ++i) {
  77.             err = AEInstallEventHandler(
  78.                 keywordsToInstall[i].theEventClass,    /* What class to install.  */
  79.                 keywordsToInstall[i].theEventID,    /* Keywords to install.    */
  80.                 keywordsToInstall[i].theHandler,    /* The AppleEvent handler. */
  81.                 0L,                                    /* Unused refcon.           */
  82.                 false                                /* Only for our app.       */
  83.             );
  84.  
  85.             if (err) {
  86.                 CenteredAlert(rErrorAlert, nil, (ModalFilterProcPtr)AlertFilter);
  87.                 return;
  88.             }
  89.         }
  90.     }
  91. }
  92.  
  93.  
  94.  
  95. /*****************************************************************************/
  96.  
  97.  
  98.  
  99. /* Send some type of message to the application we are connected to.  Most of the
  100. ** targeting information is the same for various different messages.  Given this,
  101. ** this function builds an AppleEvent, adds the common information to the AppleEvent,
  102. ** and then switches for the various different message types.  A similar factoring
  103. ** process is done at the receiving end. */
  104.  
  105. #pragma segment AppleEvents
  106. OSErr    SendMessage(FileRecHndl frHndl, short messageType)
  107. {
  108.     AEAddressDesc    remoteLoc;
  109.     OSErr            err;
  110.     AppleEvent        theAevt, reply;
  111.     long            windTag[2];
  112.     short            i;
  113.     WindowPtr        oldPort;
  114.     TEHandle        te;
  115.     char            hstate;
  116.     Handle            hText;
  117.     StScrpHandle    styl;
  118.     long            size;
  119.  
  120.     if (!(*frHndl)->connect.connected) return(noErr);
  121.  
  122.     oldPort = SetFilePort(frHndl);
  123.  
  124.     theAevt.dataHandle = reply.dataHandle = nil;
  125.         /* Make sure disposing of the descriptors is okay in all cases. */
  126.         /* Even though the AppleEvent manager nils out the handle upon failure,
  127.         ** the below code doesn't necessarily call the AppleEvent manager for each
  128.         ** descriptor.  By etting them to nil here, this allows us to just try to
  129.         ** dispose of the descriptors at the bottom of the function. */
  130.  
  131.     remoteLoc = (*frHndl)->connect.remoteLoc;
  132.  
  133.     err = AECreateAppleEvent(        /* CREATE EMPTY APPLEEVENT.     */
  134.         kCustomEventClass,            /* Event class.                 */
  135.         typeAppMessage,                /* Event ID.                 */
  136.         &remoteLoc,                    /* Address of receiving app. */
  137.         kAutoGenerateReturnID,        /* This value causes the     */
  138.                                     /* AppleEvent manager to     */
  139.                                     /* assign a return ID that     */
  140.                                     /* is unique to the session. */
  141.         kAnyTransactionID,            /* Ignore transaction ID.     */
  142.         &theAevt                    /* Location of event.         */
  143.     );
  144.  
  145.     if (!err)            /* Say what the message is. */
  146.         AEPutParamPtr(&theAevt,keyDirectObject, typeShortInteger, (Ptr)&messageType, sizeof(short));
  147.  
  148.     if (!err) {            /* Say what window message is for. */
  149.         for (i = 0; i < 2; ++i) windTag[i] = (*frHndl)->connect.windowTag[i];
  150.         AEPutParamPtr(&theAevt, keyWindowTag, typeDoubleLong, (Ptr)windTag, 2 * sizeof(long));
  151.     }
  152.  
  153.     /* The stuff that applies to all messages is now done.  Now specifically
  154.     ** handle all the different message types. */
  155.  
  156.     if (!err) {
  157.         switch (messageType) {
  158.  
  159.             case kDisconnectMssg:
  160.                     /* All the information we need is already in the AppleEvent. */
  161.                 break;
  162.  
  163.             case kTextMssg:
  164.                 te     = (*frHndl)->d.doc.outBox;
  165.                 hText  = (*te)->hText;
  166.                 hstate = LockHandleHigh(hText);
  167.                 size   = (*te)->teLength;
  168.                 err = AEPutParamPtr(
  169.                     &theAevt,
  170.                     keyAppMessage,
  171.                     typeTextMessage,
  172.                     *hText,
  173.                     size
  174.                 );
  175.                 HSetState(hText, hstate);
  176.                 break;
  177.  
  178.             case kStylMssg:
  179.                 styl = CTEGetFullStylScrap((*frHndl)->d.doc.outBox);
  180.                 if (styl) {
  181.                     LockHandleHigh((Handle)styl);
  182.                     size = GetHandleSize((Handle)styl);
  183.                     err = AEPutParamPtr(
  184.                         &theAevt,
  185.                         keyAppMessage,
  186.                         typeStylMessage,
  187.                         (Ptr)*styl,
  188.                         size
  189.                     );
  190.                     DisposeHandle((Handle)styl);
  191.                 }
  192.                 break;
  193.         }
  194.     }
  195.  
  196.     if (!err) {        /* If everything looks good... */
  197.         err = AESend(                    /* SEND APPLEEVENT.                */
  198.             &theAevt,                    /* Our Apple Event to send.        */
  199.             &reply,                        /* We may have a reply.            */
  200.             kAENoReply,                    /* Don't wait for reply.        */
  201.             kAENormalPriority,            /* App. send priority.            */
  202.             0,                            /* We aren't waiting.            */
  203.             nil,                        /* No wait, no filter.            */
  204.             nil                            /* EventFilterProcPtr.            */
  205.         );
  206.     }
  207.  
  208.     if (!err) {
  209.         if (messageType == kTextMssg)
  210.             CTESetSelect(0, (*te)->teLength, te);
  211.                 /* Select all the text so entering the next message  is more convenient. */
  212.     }
  213.  
  214.     AEDisposeDesc(&theAevt);
  215.     AEDisposeDesc(&reply);
  216.         /* Dispose of the descriptors, created or not.  If not created, no harm done by calling. */
  217.  
  218.     SetPort(oldPort);
  219.     return(err);
  220. }
  221.  
  222.  
  223.  
  224. /*****************************************************************************/
  225.  
  226.  
  227.  
  228. #pragma segment AppleEvents
  229. static pascal OSErr    ReceiveMessage(AppleEvent *message, AppleEvent *reply, long refcon)
  230. {
  231. #pragma unused (reply, refcon)
  232.  
  233.     OSErr            err;
  234.     short            messageType;
  235.     WindowPtr        window;
  236.     FileRecHndl        frHndl;
  237.     DescType        actualType;
  238.     long            actualSize, windTag[2];
  239.     AEAddressDesc    remoteLoc;
  240.     Handle            mssgData;
  241.     StScrpHandle    stylData;
  242.     TEHandle        te;
  243.     char            hstate;
  244.     long            mssgSize, stylSize;
  245.  
  246.     err = AEGetParamPtr(        /* GET THE MESSAGE TYPE.     */
  247.         message,                /* The AppleEvent.              */
  248.         keyDirectObject,        /* AEKeyword                 */
  249.         typeShortInteger,        /* Desired type.             */
  250.         &actualType,            /* Type code.                 */
  251.         (Ptr)&messageType,        /* Pointer to area for data. */ 
  252.         2 * sizeof(long),        /* Size of data area.         */
  253.         &actualSize                /* Returned size of data.     */
  254.     );
  255.  
  256.     if (!err) {
  257.         err = AEGetParamPtr(        /* GET WINDOW MESSAGE IS FOR. */
  258.             message,                /* The AppleEvent.               */
  259.             keyWindowTag,            /* AEKeyword                  */
  260.             typeDoubleLong,            /* Desired type.              */
  261.             &actualType,            /* Type code.                  */
  262.             (Ptr)windTag,            /* Pointer to area for data.  */ 
  263.             2 * sizeof(long),        /* Size of data area.          */
  264.             &actualSize                /* Returned size of data.      */
  265.         );
  266.     }
  267.  
  268.     if (!err) {            /* See if the requested window exists... */
  269.         if (window = GetAEWindow(windTag[1], windTag[0])) {
  270.             frHndl = (FileRecHndl)GetWRefCon(window);
  271.                 /* The window still exists... */
  272.         }
  273.         else
  274.             err = userCanceledErr;
  275.                 /* User (or computer) canceled connection by disconnecting improperly. */
  276.     }
  277.  
  278.     if (!err) {        /* If everything is cool, then do the specific task... */
  279.  
  280.         switch(messageType) {
  281.  
  282.             case kDisconnectMssg:
  283.                 remoteLoc = (*frHndl)->connect.remoteLoc;
  284.                 AEDisposeDesc(&remoteLoc);
  285.                 (*frHndl)->connect.connected = false;
  286.                 break;
  287.  
  288.             case kTextMssg:
  289.                 if (!err) {        /* Determine the size of the data... */
  290.                     err = AEGetParamPtr(
  291.                         message,                /* The AppleEvent.              */
  292.                         keyAppMessage,            /* AEKeyword                 */
  293.                         typeTextMessage,        /* Desired type.             */
  294.                         &actualType,            /* Type code.                 */
  295.                         nil,                    /* Pointer to area for data. */ 
  296.                         0,                        /* Size of data area.         */
  297.                         &mssgSize                /* Returned size of data.     */
  298.                     );
  299.                 }
  300.                 mssgData = nil;
  301.                 if (!err) {        /* Get the data... */
  302.                     mssgData = NewHandle(mssgSize);
  303.                     if (mssgData) {
  304.                         hstate = LockHandleHigh(mssgData);
  305.                         err = AEGetParamPtr(
  306.                             message,                /* The AppleEvent.              */
  307.                             keyAppMessage,            /* AEKeyword                 */
  308.                             typeTextMessage,        /* Desired type.             */
  309.                             &actualType,            /* Type code.                 */
  310.                             *mssgData,                /* Pointer to area for data. */ 
  311.                             mssgSize,                /* Size of data area.         */
  312.                             &actualSize                /* Returned size of data.     */
  313.                         );
  314.                         HSetState(mssgData, hstate);
  315.                     }
  316.                     else err = memFullErr;
  317.                 }
  318.                 if (!err) {
  319.                     BeginContent(window);
  320.                         /* Clip out all but content portion of the window. */
  321.  
  322.                     te       = (*frHndl)->d.doc.inBox;
  323.                     stylData = (*frHndl)->d.doc.textStyl;
  324.                     mssgData = CTESwapText(te, mssgData, stylData, true);
  325.                     if (stylData) {
  326.                         DisposeHandle((Handle)stylData);
  327.                         (*frHndl)->d.doc.textStyl = nil;
  328.                     }
  329.  
  330.                     EndContent(window);
  331.                         /* Fix the window back to normal. */
  332.                 }
  333.  
  334.                 if (mssgData)
  335.                     DisposHandle(mssgData);
  336.  
  337.                 if (!err)
  338.                     NotifyUser();
  339.  
  340.                 break;
  341.  
  342.             case kStylMssg:
  343.                 if (!err) {        /* Determine the size of the data... */
  344.                     err = AEGetParamPtr(
  345.                         message,                /* The AppleEvent.              */
  346.                         keyAppMessage,            /* AEKeyword                 */
  347.                         typeStylMessage,        /* Desired type.             */
  348.                         &actualType,            /* Type code.                 */
  349.                         nil,                    /* Pointer to area for data. */ 
  350.                         0,                        /* Size of data area.         */
  351.                         &stylSize                /* Returned size of data.     */
  352.                     );
  353.                 }
  354.                 stylData = nil;
  355.                 if (!err) {        /* Get the data... */
  356.                     stylData = (StScrpHandle)NewHandle(stylSize);
  357.                     if (stylData) {
  358.                         hstate = LockHandleHigh((Handle)stylData);
  359.                         err = AEGetParamPtr(
  360.                             message,                /* The AppleEvent.              */
  361.                             keyAppMessage,            /* AEKeyword                 */
  362.                             typeTextMessage,        /* Desired type.             */
  363.                             &actualType,            /* Type code.                 */
  364.                             (Ptr)*stylData,            /* Pointer to area for data. */ 
  365.                             stylSize,                /* Size of data area.         */
  366.                             &actualSize                /* Returned size of data.     */
  367.                         );
  368.                         HSetState((Handle)stylData, hstate);
  369.                         (*frHndl)->d.doc.textStyl = stylData;
  370.                     }
  371.                     else err = memFullErr;
  372.                 }
  373.                 break;
  374.  
  375.         }
  376.     }
  377.  
  378.     return(err);
  379. }
  380.  
  381.  
  382.  
  383.